package com.carlos.company.security.filter;

import cn.hutool.jwt.*;
import com.carlos.company.config.JwtConfig;
import com.carlos.company.security.JsonAuthentication;
import com.carlos.company.service.SysUserRoleService;
import com.carlos.company.vo.ResultVO;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.web.authentication.www.BasicAuthenticationFilter;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Objects;

/**
 * @author 李健成
 * @date 2021/10/15
 */

@Slf4j
public class AuthenticationFilter extends BasicAuthenticationFilter {

    @Autowired
    private JwtConfig jwtConfig;

    @Autowired
    private SysUserRoleService sysUserRoleService;

    public AuthenticationFilter(AuthenticationManager authenticationManager) {
        super(authenticationManager);
    }

    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain)
            throws IOException, ServletException {

        log.info("Jwt 过滤器执行...");

        String jwtStr = request.getHeader(jwtConfig.getHeader());

        // 如果无 Token
        if (Objects.isNull(jwtStr)) {
            chain.doFilter(request, response);
            return;
//            throw new JWTException("无Token");
        }

        JWT jwt = JWT.of(jwtStr);

        if (!jwt.validate(0L)) {
//            throw new JWTException("Token 校验失败");
            new ResultVO<Void>().fail("Token校验失败");
            JsonAuthentication.writeJson(request, response, new ResultVO<Void>().fail("Token校验失败"));
//            throw new JWTException("Token 校验失败");
        }

        List<GrantedAuthority> authorities = new ArrayList<>(2);

        String username = jwt.getPayload("username").toString();
        for (String role : sysUserRoleService.listRoleCodeByUsername(username)) {
            authorities.add(new SimpleGrantedAuthority(role));
        }

        UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken(username, null, authorities);

        SecurityContextHolder.getContext().setAuthentication(token);

        log.info("Jwt 过滤器完成");
        log.info("{} -- {}", username, authorities);

        chain.doFilter(request, response);
    }

}
